package cn.fangline.wo.task.akka.actors;

import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import cn.fangline.base.util.Constants;
import cn.fangline.base.util.HeaderUtil;
import cn.fangline.base.util.StringUtil;
import cn.fangline.base.util.exception.WrongContainException;
import cn.fangline.wo.model.OriginHouse;
import cn.fangline.wo.task.akka.messages.AgentHousePage;
import com.google.common.util.concurrent.RateLimiter;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Created by 抽离 on 2017/6/21 0021.
 */
public class HouseActor extends AbstractActor {

    private RateLimiter rateLimiter;

    private ActorRef housePackRef;

    private final static Logger logger = Logger.getLogger(HouseActor.class);


    public static final int RETRY_COUNTER = 10;//重试次数
    public static final int RETRY_COUNTER_REDUCE_STEP_CONNECT = 1;
//    public static AtomicInteger countSuccess  = new AtomicInteger();
//    public static AtomicInteger countFailure = new AtomicInteger();
//    public static  AtomicInteger countValidate = new AtomicInteger();
//    public  static  AtomicInteger countTimeOut = new AtomicInteger();
//    public  static  AtomicInteger count404 = new AtomicInteger();
//    public  static  AtomicInteger count429 = new AtomicInteger();
//    public  static  AtomicInteger count503 = new AtomicInteger();


    public HouseActor(RateLimiter rateLimiter, ActorRef housePackRef) {
        this.rateLimiter = rateLimiter;
        this.housePackRef = housePackRef;
    }

    @Override
    public Receive createReceive() {
        return
                receiveBuilder()
                        .match(AgentHousePage.class, this::onReceiveHousePage)
                        .build();

    }


    private void onReceiveHousePage(AgentHousePage agentHousePage) {
            rateLimiter.acquire();//阻塞
            String entry = null;
            Integer counter = agentHousePage.getCounter();
            if(counter > RETRY_COUNTER){
                return;
            }
            if(agentHousePage.getPage() == 1) {
                entry = agentHousePage.getUrl().replaceAll("https", "http");
            }
            else {
//                System.out.println("进入的HousePage：" + agentHousePage);
                entry = agentHousePage.getUrl().replaceAll("https", "http") + "p" + agentHousePage.getPage();
            }

            if(StringUtil.isNotEmpty(agentHousePage.getNextUrl())){
                entry = agentHousePage.getNextUrl();
            }
            try {
//                try {
//                    TimeUnit.MILLISECONDS.sleep(350L);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
                if(entry==null){
                    System.out.println("----------=" + agentHousePage.getUrl() + "originUserId"  + agentHousePage.getOriginUserId() + "page" + agentHousePage.getPage());
                }
                Document doc = Jsoup.connect(entry)
                        .userAgent(HeaderUtil.getUserAgent())
                        .proxy(new Proxy(Proxy.Type.HTTP
                                , new InetSocketAddress("proxy.abuyun.com", 9010)))
                        .header("Proxy-Authorization", "Basic SE80MDNUNzI3V1QwOThXUDozQzRBOTUxM0RCQ0EyQUZG")
                        .header("Proxy-Switch-Ip", "yes")
//                                    , new InetSocketAddress("proxy.abuyun.com", 9020)))
//                        .header("Proxy-Authorization", "Basic SDE1N1g0NTAxMDk4MkxFRDo5NjE3QzI4Njg1MzQ5NjM1")
                        .timeout(3000)
                        .get();


                Elements verify = doc.select("#verify_page");
                if(verify!=null && verify.size()>0){
                    throw new WrongContainException("请求频繁页面，重试");
                }

                if(StringUtil.isEmpty(doc.select(".nodt-content").toString())){
                    counter = RETRY_COUNTER + 1;
                }

                Elements elements = doc.select("#houselist-mod>li");
                if(elements==null
                        || elements.size()<=0
                        || StringUtil.isEmpty(elements.toString())){
                    return;
                }

                String next = null;
                if(doc.select(".aNxt") != null){
                    Elements nextElements = doc.select(".aNxt");
                    if(nextElements !=null && StringUtil.isNotEmpty(nextElements.toString())){
                        next = nextElements.get(0).attr("href");
                    }
                }
//                List<OriginHouse> originHouses = new ArrayList<>();
                for (Element element : elements) {
                    String title = element.select(".house-details .house-title a").first().text().replaceAll("[   ]","").trim();
                    OriginHouse originHouse = new OriginHouse();
                    originHouse.setTitle(StringUtil.filterEmoji(title));
                    originHouse.setImgUrl(element.select(".item-img img").attr("src").replaceAll("[   ]","").trim());
                    String houseTitle = element.select("a.houseListTitle").first().attr("href").replaceAll("[   ]","").trim();
                    originHouse.setNet(Constants.ANJUKE);
                    originHouse.setUrl(houseTitle.replaceAll("\\?from.*","").replaceAll("[   ]","").trim()
                    );
                    originHouse.setOriginHouseId(
                            houseTitle.replaceAll("\\.html.*","")
                                    .replaceAll("http.*gongsi-esf/","")
                                    .replaceAll("[   ]","").trim()
                    );
                    originHouse.setTotalPrice(Float.parseFloat(element.select(".price-det>strong").text().replaceAll("[   ]","").trim()));
                    Element houseDescEle = element.select(".house-details>.details-item").first();
                    originHouse.setArea(Float.parseFloat(houseDescEle.select("span").first().text().replace("m²", "").replaceAll("[   ]","").trim()));

                    String roomAndHall = houseDescEle.select("span").get(1).text().replaceAll("[   ]","").trim();
                    Integer room=null, hall=null, toilet=null;
                    if(StringUtils.isNotEmpty(roomAndHall)){
                        String reg = "((\\d+)\\u5ba4)*((\\d+)\\u5385)*((\\d+)\\u536b)*";
                        Pattern p = Pattern.compile(reg);
                        Matcher m = p.matcher(roomAndHall);
                        if(m.find()){
                            try{hall = Integer.parseInt(m.group(4));}catch (Exception e){}
                            try{room = Integer.parseInt(m.group(2));}catch (Exception e){}
                            try{toilet = Integer.parseInt(m.group(6));}catch (Exception e){}
                        }
                    }
                    originHouse.setRoom(room);
                    originHouse.setHall(hall);
                    originHouse.setToilet(toilet);

                    Integer unitPrice = null;
                    String floor = null;
                    Integer buildYear = null;
                    try {
                        unitPrice = Integer.parseInt(houseDescEle.select("span").get(2).text().replace("元/m²", "").replaceAll("[   ]","").trim());
                    }catch (Exception e){

                    }

                    try {
                        floor = houseDescEle.select("span").get(3).text();
                    }catch (Exception e){

                    }

                    try {
                        buildYear = Integer.parseInt(houseDescEle.select("span").get(4).text().replace("年建造", "").replaceAll("[   ]","").trim());
                    }catch (Exception e){

                    }

                    originHouse.setUnitPrice(unitPrice);
                    originHouse.setFloor(floor);
                    originHouse.setBuildYear(buildYear);

                    originHouse.setCityId(agentHousePage.getCityId());
                    originHouse.setOriginUserId(agentHousePage.getOriginUserId());

                    String s = element.select(".comm-address").attr("title");
                    String section = s.replaceAll("\\[.*\\]","").replaceAll("[   ]","").trim();
                    String address = s.replaceAll("^.*\\[","").replaceAll("]","").replaceAll("[   ]","").trim();
                    originHouse.setAddress(address);
                    originHouse.setSection(section);
                    originHouse.setCreateTime(new Date());
                    originHouse.setFromUrl(entry);

                    try{
//                        originHouse.insert();
                        originHouse.setUserId(agentHousePage.getUserId());
                        originHouse.setCorpId(agentHousePage.getCorpId());
                        housePackRef.tell(originHouse, getSelf());
//                        getSender().tell(new EndPoint(), getSelf());
                    }catch(Exception e){
                        System.out.println("insert exception");
                    }

//                    originHouses.add(originHouse);
                }


                if(StringUtil.isNotEmpty(next)) {
                    AgentHousePage housePage = new AgentHousePage();
                    housePage.setUrl(agentHousePage.getUrl());
                    housePage.setUserId(agentHousePage.getUserId());
                    housePage.setPage(agentHousePage.getPage() + 1);
                    housePage.setCounter(Constants.INITIAL_RETRY_COUNT);
                    housePage.setCityId(agentHousePage.getCityId());
                    housePage.setOriginUserId(agentHousePage.getOriginUserId());
                    housePage.setNextUrl(next);
                    housePage.setCorpId(agentHousePage.getCorpId());
                    getSender().tell(housePage, getSelf());
//                    executorService.execute(new HouseTask(cityId, url, originUserId, page + 1, 1, next));//必须有下一页才会去采集
                }

//                System.out.println("爬取房源成功 anjuke: "+ entry +"===耗时" + (System.currentTimeMillis() - begin) + "ms");
//                countSuccess.getAndIncrement();
            }catch (WrongContainException | IOException e){

                if(e instanceof WrongContainException){
//                    countValidate.getAndIncrement();
//                    System.out.println("出现验证码页面，" + entry);
                }

//                if(e instanceof  ConnectTimeoutException || e instanceof SocketTimeoutException){
//                    countTimeOut.getAndIncrement();
////                    System.out.println("连接超时:" + e.getMessage()  + "，" + entry);
//                }

                if(e instanceof HttpStatusException){
                    HttpStatusException ex = (HttpStatusException) e;
                    if(ex.getStatusCode() ==402){

                    }
                    if(ex.getStatusCode() == 404){
                        counter = counter + RETRY_COUNTER_REDUCE_STEP_CONNECT;
//                     count404.getAndIncrement();
                    }
                    if(ex.getStatusCode() == 429){
//                        count429.getAndIncrement();
                    }
                    if(ex.getStatusCode() == 503){
//                        count503.getAndIncrement();
                    }
//                    System.out.println("爬取出错：" + ex.getMessage() + ex.getStatusCode() + "错误url，" + ex.getUrl() + "，爬取url:" + entry);
                }

//                counter = counter + RETRY_COUNTER_REDUCE_STEP_CONTAIN;

                if(counter <= 10){
//                    System.out.println("进行重试，" + entry);
//                    executorService.execute(new HouseTask(cityId, url, originUserId, page ,counter + RETRY_COUNTER_REDUCE_STEP_CONNECT));
                    agentHousePage.setCounter(counter);
                    getSender().tell(agentHousePage, getSelf());
//                 executorService.execute(new HouseTask(cityId, url, originUserId, page ,counter));
                }
            }
            catch (Exception e){
//              mainGather.switchIp();
                if(counter <= 10){
//                    System.out.println("进行第" + counter + "次重试，" + entry);
                    agentHousePage.setCounter(counter +1);
                    getSender().tell(agentHousePage, getSelf());
//                    executorService.execute(new HouseTask(cityId, url, originUserId, page ,counter + RETRY_COUNTER_REDUCE_STEP_CONNECT));
                }else{
//                    countFailure.getAndIncrement();
//                    logger.error(entry+"爬取出错" + "已重试次数：" + counter);
                    StringWriter errors = new StringWriter();
                    e.printStackTrace(new PrintWriter(errors));
                    logger.error(new StringBuilder()
                            .append("安居客房源列表爬取出错").append("\n")
                            .append("from url: ").append(agentHousePage.getUrl()).append("\n")
                            .append("e StackTrace: "+ errors));
                }
            }
    }


}
